package vip.meeet.jdk.collections;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class EvictingArray<T> implements Serializable {

    private static final long serialVersionUID = 0L;

    private Object[] elements;

    private int index;

    private int capacity;

    private int size;

    private EvictingArray() {
    }

    public static EvictingArray create(int capacity){
        return new EvictingArray(capacity);
    }

    public EvictingArray(int capacity) {
        this.elements = new Object[capacity];
        this.capacity = capacity;
        this.size = 0;
        this.index = 0;
    }

    public synchronized void add(T element){
        elements[index++ % capacity] = element;
        if(size < capacity){
            size++;
        }
    }

    public List<T> getAll(){
        LinkedList<T> data = new LinkedList();
        int i = 0;
        int curSize = size;
        int curIndex = index;
        while (curSize-- > 0){
            data.add((T) elements[curIndex++ % capacity]);
        }
        return data;
    }

    public void clear(){
        this.size = 0;
        this.index = 0;
    }

    public int getSize() {
        return size;
    }

    public static void main(String[] arg){
        EvictingArray<Integer> queue = EvictingArray.create(3);
        queue.add(1);
        queue.add(2);
        queue.add(3);
        queue.add(4);
        queue.getAll().forEach(item -> System.out.print(item + " "));
        System.out.println("---------");
        queue.add(5);
        queue.add(6);
        queue.getAll().forEach(item -> System.out.print(item + " "));
        System.out.println("---------");
        queue.add(8);
        queue.add(9);
        queue.getAll().forEach(item -> System.out.print(item + " "));
    }
//public static void main(String[] arg){
//        EvictingArray<Integer> queue = EvictingArray.create(10);
//        ExecutorService executorService = Executors.newFixedThreadPool(10);
//        for(int i=0;i<10;i++){
//            executorService.submit(new Producer(queue));
//        }
//        new Thread(new Consumer(queue)).start();
//    }

    private static class Producer implements Runnable{

        private EvictingArray<Integer> array;

        public Producer(EvictingArray<Integer> array) {
            this.array = array;
        }

        @Override
        public void run() {
            Random random = new Random();
            while (true){
                array.add(random.nextInt(100));
            }
        }
    }

    private static class Consumer implements Runnable{

        private EvictingArray<Integer> array;

        public Consumer(EvictingArray<Integer> array) {
            this.array = array;
        }

        @Override
        public void run() {
            while (true){
                array.getAll().forEach(item -> System.out.print(item + " "));
                System.out.println("----------");
            }
        }
    }
}
